//常见的IO头文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "singlelinklist.h"

int main(int argc, char const *argv[])
{
    p_linklist HEAD=NULL;
    //指定位置插入测试
    HEAD=list_Create();
     //尾插
     printf("尾插法插入1,2,3,4\n");
     list_tail_insert(HEAD,1);
     list_tail_insert(HEAD,2);
     list_tail_insert(HEAD,3);
     list_tail_insert(HEAD,4);
      //遍历
    list_show(HEAD);
    printf("\n");


    printf("list_insert将5插入第1个位置\n");
    list_insert(HEAD,5,1);//在第一个位置插入
    list_show(HEAD);
    printf("\n");

    printf("list_insert将6插入第6个位置\n");
    list_insert(HEAD,6,6);//在最后一个位置插入
    list_show(HEAD);
    printf("\n");

    printf("list_insert将6插入第10个位置(非法)\n");
    list_insert(HEAD,6,10);//在非法位置插入
    list_show(HEAD);
    printf("\n");

    printf("list_insert将100插入第4个位置\n");
    list_insert(HEAD,100,4);//在中间位置插入
    list_show(HEAD);
    printf("\n");


    //删除测试
    printf("删除指定位置的元素:\n");
    printf("删除第1个位置:\n");
    list_delete(HEAD,1);
    list_show(HEAD);
    printf("\n");

    printf("删除第6个位置:\n");
    list_delete(HEAD,6);
    list_show(HEAD);
    printf("\n");

    printf("删除第3个位置:\n");
    list_delete(HEAD,3);
    list_show(HEAD);
    printf("\n");

    printf("删除第6个位置:\n");
    list_delete(HEAD,6);
    list_show(HEAD);
    printf("\n");

    printf("删除第5个位置:\n");
    list_delete(HEAD,5);
    list_show(HEAD);
    printf("\n");

    printf("修改第1个位置:\n");
    list_Change(HEAD,1,99);
    list_show(HEAD);
    printf("\n");

    printf("修改第7个位置:\n");
    list_Change(HEAD,7,99);
    list_show(HEAD);
    printf("\n");

    printf("修改第4个位置:\n");
    list_Change(HEAD,4,8);
    list_show(HEAD);
    printf("\n");

    printf("修改第5个位置:\n");
    list_Change(HEAD,5,8);
    list_show(HEAD);
    printf("\n");

    //销毁
    HEAD=list_free(HEAD);
    list_show(HEAD);
    
    return 0;
}

//创建一个空链表
p_linklist list_Create()
{
    p_linklist head=NULL;//定义一个头结点  是一个空指针
    head=(p_linklist)malloc(sizeof(Lnode));//向堆区申请一段空间
    //判断是否申请空间成功
    if(head==NULL)
    {
        printf("malloc faild\n");
        return NULL;
    }
    //由于我们创建的是一个带头结点的链表   头结点将不会用来存储数据
    head->data=0;
    head->next=NULL;
    return head;
}
//尾插  -1:失败
int list_tail_insert(p_linklist H, DATA_TYPE value)//head
{
    //链表是否存在
    if(H==NULL)
    {
        printf("list is error\n");//链表不存在
        return -1;
    }
    //创建一个新的结点
    p_linklist newnode =(p_linklist)malloc(sizeof(Lnode)) ; 
    if(newnode==NULL)
    {
        printf("newnode malloc faild\n");
        return -1;
    }
    //将新数据给新结点
    newnode->data=value;
    newnode->next=NULL;//指针域为空
    //找到尾  遍历
    p_linklist p_head=H;//从头结点开始遍历
    while(p_head->next!=NULL)
    {
        p_head=p_head->next;
    }
    //当前phead指向的是尾节点
    p_head->next=newnode;//建议连接

    return 0;
}
//获得指定位置的结点
p_linklist list_get(p_linklist H, int pos)//通过pos 获得第pos个位置的结点
{
    //自己写一下
}
//头插
int list_head_insert(p_linklist H, DATA_TYPE value)
{
    //链表是否存在
    if(H==NULL)
    {
        printf("list is error\n");//链表不存在
        return -1;
    }
     //创建一个新的结点
     p_linklist newnode =(p_linklist)malloc(sizeof(Lnode)) ; 
     if(newnode==NULL)
     {
         printf("newnode malloc faild\n");
         return -1;
     }
     //将新数据给新结点
     newnode->data=value;
     newnode->next=NULL;//指针域为空
     //更新结点指针操作
     //先让新节点的指针域 指向头结点的下一个结点
     newnode->next=H->next;
     //再让头结点指向新节点
     H->next=newnode;
     return 0;

}
//指定位置插入 //将value插入到第pos结点之前 pos从1开始
int list_insert(p_linklist H, DATA_TYPE value, int pos)
{
     //链表是否存在
     if(H==NULL)
     {
         printf("list is error\n");//链表不存在
         return -1;
     }
     //pos位置要不要判断
     if(pos<1)
     {
        printf("pos is error\n");
        return -1;
     }
    //如果是第一个结点之前插入  就是头插
    if(pos==1)
    {
        list_head_insert(H,value);//头插
        return 0;
    }
     //找pos的位置
     p_linklist phead=H->next;//从头结点的下一个结点开始查找
     int i=1;
     while (i<pos-1)//i<1
     {
        /* code */
        phead=phead->next;
        if(phead==NULL)
        {
            printf("pos is too large\n");
            return -1;
        }
        i++;
     }
     //printf("phead->data:%d\n",phead->data);//测试找pos的前一个结点的
     //如果phead->next为空 表示 是尾插
     if(phead->next==NULL)
     {
        printf("尾插\n");
        list_tail_insert(H,value);//尾插
        return 0;
     }

    //创建一个新的结点
    p_linklist newnode =(p_linklist)malloc(sizeof(Lnode)) ; 
    if(newnode==NULL)
    {
        printf("newnode malloc faild\n");
        return -1;
    }
    //将新数据给新结点
    newnode->data=value;
    newnode->next=NULL;//指针域为空
    //进行数据的插入
   newnode->next=phead->next;//将新节点与原来的pos个结点进行连接
   phead->next=newnode;//原来的pos的前一个结点  连接 新节点

   return 0;

}
//销毁链表
p_linklist list_free(p_linklist H)
{
    //链表是否存在
    if(H==NULL)
    {
        printf("list is error\n");//链表不存在
        return NULL;
    }
    p_linklist phead=H->next,temp;
    while(phead!=NULL)
    {
        //先存起来 phead
        temp=phead;
        printf("销毁的数据为%d\n",temp->data);
        phead=phead->next;
        memset(temp,0,sizeof(Lnode));
        free(temp);//释放
    }
    //释放头结点
    memset(H,0,sizeof(Lnode));
    free(H);//释放
    return NULL;
}
//删除某一个位置上的结点
int list_delete(p_linklist H, int pos)
{
    p_linklist temp;//替死鬼
     //链表是否存在
     if(H==NULL)
     {
         printf("list is error\n");//链表不存在
         return -1;
     }
     //pos位置要不要判断
     if(pos<1)
     {
        printf("pos is error\n");
        return -1;
     }
     //空表
     if(H->next==NULL)
     {
        printf("list is empty\n");
        return -1;
     }
     //找结点
      //如果是第一个结点之前插入  就是删除第一个结点
    if(pos==1)
    {
         //先保存 第一个结点   再将头结点指向 第二个结点
         temp=H->next;
         H->next=H->next->next;
         //释放 temp
         memset(temp,0,sizeof(Lnode));
         free(temp);
        return 0;
    }
     //找pos的位置
     p_linklist phead=H->next;//从头结点的下一个结点开始查找
     int i=1;
     while (i<pos-1)//i<1
     {
        /* code */
        phead=phead->next;
        if(phead==NULL)
        {
            printf("pos is too large\n");
            return -1;
        }
        i++;
     }
     //printf("phead->data:%d\n",phead->data);//测试找pos的前一个结点的
     //如果phead->next为空 表示找的这个结点是第pos-1个结点 它是尾节点 无法删除  所以位置错误
     if(phead->next==NULL)
     {
        printf("delete error\n");
        return -1;
     }

    //进行结点的删除
    temp=phead->next;//保存要删除的结点
    phead->next=temp->next;
    //释放temp
    memset(temp,0,sizeof(Lnode));
    free(temp);

   return 0;
}
//修改结点数据
int list_Change(p_linklist H,DATA_TYPE value,DATA_TYPE newvalue)
{
    //链表是否存在
    if(H==NULL)
    {
        printf("list is error\n");//链表不存在
        return -1;
    }
    //value位置要不要判断
    if(value<1)
    {
       printf("value is error\n");
       return -1;
    }
     //找value的位置
     p_linklist phead=H->next;//从头结点开始查找
     int i=1;
     while (phead != NULL && i < value)//i<=1
     {
        phead = phead->next;
        i++;
     }
    if (phead == NULL) {
        printf("位置超出链表长度\n");
        return -1;
    }


    phead->data = newvalue;

    return 0;
}
// 遍历链表
int list_show(p_linklist H)
{
    //判空 判断链表是否存在
    if(H==NULL)
    {
        printf("list is error\n");
        return -1;
        
    }
    //因为是带头结点的单链表
    if(H->next==NULL)
    {
        printf("list is empty\n");
        return -1;
    }
    printf("遍历: ");
    //遍历
    p_linklist phead=H->next;//可以从下一个结点开始遍历
    while(phead)
    {
        printf("%d ",phead->data);
        phead=phead->next;
    }
    printf("\n");
    return 0;

}
